package edu.pku.sei.mte.mtemodel.mtmodel.rulebased;

import java.util.ArrayList;
import java.util.List;

import edu.pku.sei.mte.mtemodel.core.DataType;
import edu.pku.sei.mte.mtemodel.mtmodel.ModelType;
import edu.pku.sei.mte.mtemodel.mtmodel.common.Variable;
import edu.pku.sei.mte.mtemodel.mtmodel.expression.Expression;
import edu.pku.sei.mte.runtime.Context;
import edu.pku.sei.mte.runtime.rulebased.RBTContext;
import edu.pku.sei.mte.utilities.Visitor;

public class Relation extends Rule {
	private List<Domain> domains;
	private List<Expression> whenClause;
	private List<Expression> whereClause;
	private List<Variable> variableDeclaration;

	public List<Domain> getDomains() {
		if(domains==null){
			domains = new ArrayList<Domain>();
		}
		return domains;
	}
	
	public void addDomain(Domain domain){
		getDomains().add(domain);
		domain.setHost(this);
	}
	
	public Domain getDomain(ModelType type){
		for(Domain d : getDomains()){
			if(d.getModelType()==type)
				return d;
		}
		return null;
	}

	public List<Expression> getWhenClause() {
		if(whenClause==null){
			whenClause = new ArrayList<Expression>();
		}
		return whenClause;
	}

	public List<Expression> getWhereClause() {
		if(whereClause==null){
			whereClause = new ArrayList<Expression>();
		}
		return whereClause;
	}

	public List<Variable> getVariableDeclaration() {
		if(variableDeclaration==null){
			variableDeclaration = new ArrayList<Variable>();
		}
		return variableDeclaration;
	}
	public void declareVariable(String name,DataType type){
		declareVariable(name,type,Variable.UNINITIATED_VALUE);
	}
	public void declareVariable(String name,DataType type,Object defaultValue){
		Variable v = new Variable();
		v.setName(name);
		v.setType(type);
		v.setValue(defaultValue);
		getVariableDeclaration().add(v);
	}
	
	public void registVariableToContext(Context context){
		for(Variable v : getVariableDeclaration()){
			Variable dv = context.registVariable(v.getName(), v.getType());
			dv.setValue(v.getValue());
		}
		for(Domain d : getDomains()){
			d.getPattern().registVariableToContext(context);
		}
	}
	
	public void registVariableToContext(RBTContext context){
		context.setRule(this);
		registVariableToContext((Context)context);
	}
	
	public String toString(){
		return "Relation="+getName();
	}
	
	public void setTopLevel(boolean b){
		if(b)
			setPriority(0);
		else 
			setPriority(1);
	}
	public boolean isTopLevel(){
		return getPriority()==0;
	}
	
	@Override
	public Object accept(Visitor visitor) throws Exception {
		return visitor.visitRelation(this);
	}
}
